package com.levi.distributedjob.xxl_job;

import com.google.gson.Gson;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import com.xxl.job.core.util.ShardingUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * xxl-job分布式任务执行器
 * 现在后台管理界面创建一个任务，填写cron表达式，运行模式，jobHandler名称等
 *  @XxlJob("jobHandler") 中的名字要与后台管理设置的jobHandler的名字一样
 *
 *  xxl-job的用途：1.月初为每个用户生成上个月的结单，商城凌晨定时自动补货
 */
@Component
@Slf4j
public class XxlJobDemo {

    @XxlJob("myxxlJobHandler")
    public ReturnT<String> execute(String param) {
        log.info("myxxlJobHandler  start ....");
        XxlJobLogger.log("myxxlJobHandler  start ....");

        List<Integer> list = Arrays.asList(1, 2, 3, 4);

        /**
         * 1.轮询,流量均摊
         * 2.故障转移 ,第一个出现故障则使用后面的，否则一直使用第一台机器,这样日志全部在第一台，查日志方便
         *
         *
         * 3.使用分片广播,必须掌握，大大提高了任务处理的速度
         * ShardingVO对象包含两个属性
         * index：当前分片序号(从0开始)，执行器集群列表中当前执行器的序号；
         * total：总分片数，执行器集群的总机器数量；
         * >>>>>   对元素进行取模，选择执行的执行器    <<<<<<
         * --------------------------------------------------------------------------------------
         *阻塞处理策略
         * 1.单机串行      >>>>>>  排队，任务执行时间很长的话，阻塞时间就长
         * 2.丢弃后续调度   >>>>>>  前面有任务正在执行的话，这次执行就会失败    (推荐使用)
         * 3.覆盖之前调度   >>>>>>  把前面正在执行的任务中断，执行这次的任务
         */
        ShardingUtil.ShardingVO shardingVo = ShardingUtil.getShardingVo();
        for (Integer i : list) {
            if (i % shardingVo.getTotal() == shardingVo.getIndex()){
                log.info("my xxljob  execute ,user={},shadingVo={}",i,new Gson().toJson(shardingVo));
                //打印到管理界面日志
                XxlJobLogger.log("my xxljob  execute ,user={},shadingVo={}",i,new Gson().toJson(shardingVo));
            }
        }
        return ReturnT.SUCCESS;
    }

}
